package com.wisdom.system.common.util;

import com.wisdom.system.common.exception.LogicException;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {

    private final static SimpleDateFormat DATE = new SimpleDateFormat("yyyy-MM-dd");
    private final static SimpleDateFormat DATE_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private final static SimpleDateFormat HM_DATE_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private final static SimpleDateFormat HH_DATE_TIME = new SimpleDateFormat("yyyy-MM-dd HH");
    private final static SimpleDateFormat TIME = new SimpleDateFormat("HH:mm:ss");
    private final static SimpleDateFormat HH = new SimpleDateFormat("HH");
    private final static SimpleDateFormat HM = new SimpleDateFormat("HH:mm");

    /**
     * 上下午几时
     */
    private final static SimpleDateFormat aHH = new SimpleDateFormat("aHH", Locale.CHINA);

    public static String getNowDateTimeStr() {
        return DATE_TIME.format(new Date());
    }

    public static Date getNowDateTime() {
        return geCommonDateTime(getNowDateTimeStr());
    }

    public static Date getNowDate() {
        return getDate(getNowDateStr());
    }

    public static String getNowDateStr() {
        return getDateStr(new Date());
    }

    public static String getDateTimeStr(Date date) {
        try {
            return DATE_TIME.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String getDateStr(Date date) {
        try {
            return DATE.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String getTimeStr(Date date) {
        try {
            return TIME.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取小时
     * @param date 09:00
     * @return
     */
    public static Date getHmDate(String date) {
        try {
            return HM.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *  获取小时
     * @param date 09:00
     * @return
     */
    public static String getHmDateStr(Date date) {
        try {
            return HM.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
    public static String getAHmDateStr(Date date) {
        try {
            return aHH.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static Date getDate(String date) {
        try {
            return DATE.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date geCommonDateTime(String date) {
        try {
            return DATE_TIME.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date geHmDateTime(String date) {
        try {
            return HM_DATE_TIME.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 全局变量 时间格式 “yyyy-MM-dd HH:mm”
     * @param date Date类型
     * @return yyyy-MM-dd HH:mm
     */
    public static String getHhDateTime(Date date){
        try{
            return HH_DATE_TIME.format(date);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 全局变量 时间格式 “yyyy-MM-dd HH”
     * @param date Date类型
     * @return yyyy-MM-dd HH:mm
     */
    public static String getHmDateTime(Date date){
        try{
            return HM_DATE_TIME.format(date);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static Date addMinute(Date now, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }

    public static String addHour(Date now, int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.HOUR, hour);
        Date dt = calendar.getTime();
        return getDateTimeStr(dt);
    }

    /**
     * 日期加几天
     *
     * @param date
     * @param dayNum  大于0 日期加几天  小于0 日期减几天
     * @return 如 2030-11-11  -> 2030-11-12
     */
    public static String addDate(Date date, int dayNum) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.DAY_OF_YEAR, dayNum);
        Date dt = rightNow.getTime();
        return getDateStr(dt);
    }

    /**
     * 日期加几天
     *
     * @param date
     * @return 如 2030-11-11 23:59:59  -> 2030-11-12 23:59:59
     */
    public static String addDateTime(Date date, int dayNum) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.DAY_OF_YEAR, dayNum);
        Date dt = rightNow.getTime();
        return getDateTimeStr(dt);
    }

    /**
     * 日期加几秒
     *
     * @param date
     * @return 如 2030-11-11 23:59:59  -> 2030-11-12 23:59:59
     */
    public static String addSecond(Date date, int second) {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.SECOND, second);
        Date dt = rightNow.getTime();
        return getDateTimeStr(dt);
    }

    /**
     * 返回两个日期相差几天
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int dateSubDate(Date date1, Date date2) {
        String date1Str = getDateStr(date1);
        String date2Str = getDateStr(date2);
        try {
            date1 = DATE.parse(date1Str);
            date2 = DATE.parse(date2Str);
        } catch (ParseException e) {
            e.printStackTrace();
        }catch (NumberFormatException e2){
            e2.printStackTrace();
        }
        //跨年不会出现问题
        //如果时间为：2016-03-18 11:59:59 和 2016-03-19 00:00:01的话差值为 0
        double days = 1.0 * (date1.getTime() - date2.getTime()) / (1000 * 3600 * 24);
        return (int) Math.ceil(days);
    }


    /**
     * 返回两个日期相差几小时
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int dateTimeSub(Date date1, Date date2) {
        String date1Str = getDateTimeStr(date1);
        String date2Str = getDateTimeStr(date2);
        try {
            date1 = DATE_TIME.parse(date1Str);
            date2 = DATE_TIME.parse(date2Str);
        } catch (ParseException e) {
            e.printStackTrace();
        }catch (NumberFormatException e2){
            e2.printStackTrace();
        }
        //跨年不会出现问题
        //如果时间为：2016-03-18 11:59:59 和 2016-03-19 00:00:01的话差值为 0
        double days = 1.0 * (date1.getTime() - date2.getTime()) % (1000 * 3600 * 24) / (1000 * 3600);
        return (int) Math.ceil(days);
    }

    public static String getETime(String sTime,int interval) {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        String eTime = "";
        try {
            Date d = df.parse(sTime);
            d.setTime(d.getTime() + interval * 60 * 1000);
            eTime = df.format(d);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return eTime;
    }

    public static String getTimeSlot(Date time, Integer reservationSourceTimeInterval) {
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        String timeSlot = "";
        long halfHour = reservationSourceTimeInterval * 60 * 1000;
        long stamp = time.getTime();
        long startTime = stamp - stamp % halfHour;
        long endTime = startTime + halfHour;
        Date date = new Date();
        date.setTime(startTime);
        timeSlot = df.format(date);
        date.setTime(endTime);
        timeSlot += "~" + df.format(date);
        return timeSlot;
    }

    /**
     * 获取两个时间相差分钟数
     * @param start
     * @param end
     * @return 分钟数
     */
    public static int getTimeDifference(String start,String end){
        //把当前时间和要比较的时间转换为Date类型，目的在于得到这两个时间的毫秒值
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Date parse = null;
        Date now = null;
        try {
            parse = sdf.parse(start);
            now = sdf.parse(end);
        } catch (ParseException e) {
        }
        //获得这两个时间的毫秒值后进行处理(因为我的需求不需要处理时间大小，所以此处没有处理，可以判断一下哪个大就用哪个作为减数。)
        long diff = now.getTime() - parse.getTime();

        //此处用毫秒值除以分钟再除以毫秒既得两个时间相差的分钟数
        long minute = diff/60/1000;
        return (int)minute;
    }

    /**
     * 获取数组中最小时间和最大时间
     *
     * @param dateArray = {"09:00","10:00","10:00","12:00"};
     * @return min 最小时间 max 最大时间
     */
    public static Map<String,String> showResult(String[] dateArray) {
        Map<String, Integer> dateMap = new TreeMap<String, Integer>();
        int i, arrayLen;
        arrayLen = dateArray.length;
        for(i = 0; i < arrayLen; i++){
            String dateKey = dateArray[i];
            if(dateMap.containsKey(dateKey)){
                int value = dateMap.get(dateKey) + 1;
                dateMap.put(dateKey, value);
            }else{
                dateMap.put(dateKey, 1);
            }
        }
        Set<String> keySet = dateMap.keySet();
        String []sorttedArray = new String[keySet.size()];
        Iterator<String> iter = keySet.iterator();
        int index = 0;
        while (iter.hasNext()) {
            String key = iter.next();
            sorttedArray[index++] = key;
        }
        int sorttedArrayLen = sorttedArray.length;

        Map<String,String> resultMap = new HashMap(2);
        resultMap.put("min",sorttedArray[0]);
        resultMap.put("max",sorttedArray[sorttedArrayLen - 1]);
        return resultMap;
    }

    public static String getChineseTime(Date time){
        String str = HH.format(time);
        int a = Integer.parseInt(str);
        if (a >= 0 && a <= 6) {
            return "凌晨";
        }else if (a > 6 && a <= 12) {
            return "上午";
        }else  if (a > 12 && a <= 13) {
            return "中午";
        }else if (a > 13 && a <= 18) {
            return "下午";
        }else {
            return "晚上";
        }

    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param nowTime 当前时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     * @author jqlin
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }


    public static int getAgeByBirth(Date birthDay) throws ParseException {
        int age = 0;
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) {
            //出生日期晚于当前时间，无法计算
            throw new IllegalArgumentException(
                    "出生时间不能晚于当前时间!");
        }
        int yearNow = cal.get(Calendar.YEAR);  //当前年份
        int monthNow = cal.get(Calendar.MONTH);  //当前月份
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH); //当前日期
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        age = yearNow - yearBirth;   //计算整岁数
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    //当前日期在生日之前，年龄减一
                    age--;
                }
            } else {
                age--;//当前月份在生日之前，年龄减一
            }
        }
        return age;
    }


    //当前时间前几小时
    public static Date getBeforNumberTime(int beforeHourse,Date sourDate){
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(sourDate);
        calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR)-beforeHourse);
        Date date=calendar.getTime();
        return date;
    }

    /**
     * 获取时间的小时
     * @param date
     * @return
     */
    public static Integer getHour(Date date){
        if(date==null)
        {
            return null;
        }
        return getCalendar(date).get(Calendar.HOUR_OF_DAY);
    }

    public static Calendar getCalendar(Date date){
        if(date==null)
        {
            return null;
        }
        DateFormat df = DateFormat.getDateInstance();
        df.format(date);
        return df.getCalendar();
    }

    /**
     * 当前时间后几小时
     * @param calendarConst  Calendar.HOUR
     * @param afterHourse
     * @param sourDate
     * @return
     */
    public static Date getAfterNumberTime(int calendarConst, int afterHourse, Date sourDate){
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(sourDate);
        calendar.set(calendarConst, calendar.get(calendarConst)+afterHourse);
        Date date = calendar.getTime();
        return date;
    }

    //由出生日期获得年龄
    public static int getAge(Date birthDay) {
        if(null == birthDay){
            return 0;
        }
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) {
            throw LogicException.of("生日不能晚于当前日期！");
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDay);

        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

}
